package com.roomaja.roomaja.tool;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.roomaja.roomaja.Enum.WenKuDocTypeEnum;
import com.roomaja.roomaja.entity.WenKuEntity;

import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import us.codecraft.webmagic.Page;

import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import static com.roomaja.roomaja.Enum.WenKuDocTypeEnum.PPT;

/**
 * 百度文库工具类
 */
public class WenKuTool {

    //保存文件的根路径
    public static final String ROOT_PATH = System.getProperty("user.dir");
    public static final String WENKU_PATH = "/wenku_source";
    public static final String DOC_PATH = "/doc";
    public static final String PPT_PATH = "/ppt";
    public static final String PDF_PATH = "/pdf";
    public static final String TXT_PATH = "/txt";

    private static String Y = "";

    static{
        File doc = new File(ROOT_PATH+WENKU_PATH+DOC_PATH);
        File pdf = new File(ROOT_PATH+WENKU_PATH+PDF_PATH);
        File ppt = new File(ROOT_PATH+WENKU_PATH+PPT_PATH);
        File txt = new File(ROOT_PATH+WENKU_PATH+TXT_PATH);
        if(!doc.exists()){
            doc.mkdirs();
        }
        if(!pdf.exists()){
            pdf.mkdirs();
        }
        if(!ppt.exists()){
            ppt.mkdirs();
        }
        if(!txt.exists()){
            txt.mkdirs();
        }
    }

    /**
     * 相当于python 的 findall():在传进来的url中获取doc_id
     * @param regex
     * @param text
     * @return
     */
    public static List<String> findall(String regex, String text){
        Matcher matcher = Pattern.compile(regex).matcher(text);
        List<String> matchStrings = new ArrayList<String>();
        while(matcher.find()){
            matchStrings.add(matcher.group());
        }
        return matchStrings;
    }

    public static class requests{
        /**
         * 获取数据流
         * @param url
         * @return
         * @throws IOException
         * @throws URISyntaxException
         */
        public static InputStream getContent(String url){
            InputStream is = null;
            try{
                URI uri = new URI(url);
                SimpleClientHttpRequestFactory schr = new SimpleClientHttpRequestFactory();
                // 构造请求
                ClientHttpRequest chr = schr.createRequest(uri, HttpMethod.GET);
                //chr.getBody().write(param.getBytes());//body中设置请求参数
                // 发送请求
                ClientHttpResponse res = chr.execute();

                List<String> ContentEncoding = res.getHeaders().get("Content-Encoding");
                if(ContentEncoding != null && ContentEncoding.size() > 0 && "gzip".equals(ContentEncoding.get(0))){
                    //判断Content-Encoding的类型是否是gzip
                }

                is = res.getBody(); //获得返回数据,注意这里是个流
            }catch (IOException e){
                e.printStackTrace();
            }catch (URISyntaxException e1) {
                e1.printStackTrace();
            }

            return is;
        }

        /**
         * 获取文本数据
         * @param url
         * @return
         */
        public static String getText(String url) {

            String str = "";
            StringBuffer stringBuffer = new StringBuffer();
            try {

                InputStream is = getContent(url);
                InputStreamReader isr = new InputStreamReader(is,"gb2312");
                BufferedReader br = new BufferedReader(isr);
                while ((str = br.readLine()) != null) {
                    stringBuffer.append("\r\n");//换行符
                    stringBuffer.append(str);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return stringBuffer.toString();
        }

        public static String getText(String url, String charsetName, boolean isgzip) {
            String str = "";
            StringBuffer stringBuffer = new StringBuffer();
            try {

                InputStream is = getContent(url);
                InputStreamReader isr = new InputStreamReader(isgzip?new GZIPInputStream(is):is,charsetName);
                BufferedReader br = new BufferedReader(isr);
                while ((str = br.readLine()) != null) {
                    if(!isgzip){
                        stringBuffer.append("\r\n");//换行符
                    }
                    stringBuffer.append(str);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return stringBuffer.toString();
        }
    }

    //字符串转换unicode
    public static String stringToUnicode(String string) {
        StringBuffer unicode = new StringBuffer();
        for (int i = 0; i < string.length(); i++) {
            char c = string.charAt(i);  // 取出每一个字符
            unicode.append("\\u" +Integer.toHexString(c));// 转换为unicode
        }
        return unicode.toString();
    }

    //unicode 转字符串
    public static String unicodeToString(String unicode) {
        StringBuffer string = new StringBuffer();
        String[] hex = unicode.split("\\\\u");

        //若为纯字母或纯数字，不做处理
        if (hex.length == 1){
            return unicode;
        }

        for (int i = 1; i < hex.length; i++) {
            /*if (hex[i].endsWith("\\r\\n")){
                hex[i] = hex[i].replace("\\r\\n", "");
            }*/
            int data = Integer.parseInt(hex[i], 16);// 转换出每一个代码点
            string.append((char) data);// 追加成string
        }
        return string.toString();
    }

    /**
     * "c":"\u9879\u76ee\u5f00\u53d1\u603b\u7ed3\u62a5\u544a\uff08","p":{"h":15.84,"w":142.037,"x":135.036,"y":111.853,
     * 解析以上格式的字符串，获取c字段的值，以及y字段的值，并返回一个List<String>
     * @param string
     */
    private static List<String> cyList(String string){
        String c = "";
        String y = "";
        List<String> list = new ArrayList<>();
        try{
            String[] str = string.split(",");
            String[] cstr = str[0].split(":");
            if("\"c\"".equals(cstr[0])){
                c = cstr[1].replaceAll("\"","");
            }
            String[] ystr = str[str.length-1].split(":");
            if("\"y\"".equals(ystr[0])){
                y = ystr[1];
            }
        }catch (Exception e){
            System.out.println(e.getMessage());
        }
        list.add(c);
        list.add(y);

        return list;
    }

    /**
     * 保存字符文件
     * @param path
     * @param content
     */
    public static void saveString(String path, String fileName, String content){
        try{
            saveByte(path, fileName, content.getBytes("utf-8"));
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 下载数据的方法
     * @param path
     * @param fileName
     * @param bytes
     */
    public static void saveByte(String path, String fileName, byte[] bytes){
        File file = new File(path+"/"+fileName);
        FileOutputStream fileOutputStream = null;
        try{
            try{
                File tmpFile = new File(path);
                if(!tmpFile.exists()){
                    tmpFile.mkdirs();
                }
                if(!file.exists()){
                    file.createNewFile();
                }
                fileOutputStream = new FileOutputStream(file);
                fileOutputStream.write(bytes);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                fileOutputStream.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private static long createSessionID() {
        long t1 = 0x7FFFFFFF & System.currentTimeMillis();
        return t1 << 32 | Math.abs(new Random().nextInt());
    }

    public static String createRandomId(){
        return String.valueOf(createSessionID());
    }

    public static byte[] readInputStream(InputStream inStream){
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[2048];
        int len = 0;
        try{
            while( (len=inStream.read(buffer)) != -1 ){
                outStream.write(buffer, 0, len);
            }
            inStream.close();
        }catch(Exception e){
            e.printStackTrace();
        }

        return outStream.toByteArray();
    }


    public static void DOC(String url){
        StringBuffer txtBuffer = new StringBuffer();

        String docId = "";
        //List<String> matchStrings = findall("view/(.*).html",url);
        // 在url中获取doc_id
		List<String> matchStrings = findall("(?<=view/)(.*)(?=.html)",url);
        System.out.println("matchStrings = " + matchStrings.toString());
        if(matchStrings.size()!=0){
            docId = matchStrings.get(0);
//            System.out.println(docId);
        }

        // 获取文本数据：url对应的整个页面的内容
        String html = requests.getText(url);
        System.out.println("html = " + html);
        List<String> lists = findall("(https.*?0.json.*?)\\\\x22}", html);
        System.out.println("lists = " + lists.toString());
        int length = (Integer)lists.size()/2;
        List<String> newLists = lists.subList(0,length);
        for (int i = 0; i < newLists.size(); i++){
            newLists.set(i, newLists.get(i).replace("\\", ""));
            newLists.set(i, newLists.get(i).replace("x22}", ""));
            String txts = requests.getText(newLists.get(i));
            List<String> txtLists = findall("\"c\"\\:\"(.*?)\".*?\"y\"\\:(.*?),", txts);
            for (int j = 0;j < txtLists.size(); j++){
                List<String> cyList = cyList(txtLists.get(j));
                String c = cyList.get(0);
                String y = cyList.get(1);
                String n = "";
                if(!Y.equals(y) ){
                    Y = y;
                    n = "\n";
                }else {
                    n = "";
                }
                txtBuffer.append(n+unicodeToString(c));     // txtBuffer内容为页面的分析结果
            }
        }
//        System.out.println(txtBuffer.toString());
        String sourcePath = ROOT_PATH+WENKU_PATH+DOC_PATH+"/"+docId;
        String fileName = docId;
        saveString(sourcePath,fileName + ".txt",txtBuffer.toString());
        String zipFilePath = "zipPath";
        FileToZip.fileToZip(sourcePath, zipFilePath, fileName);
    }

    /**
     * 下载ppt格式的文档
     * @param url
     */
    public static void PPT(String url){
        String docId = findall("(?<=view/)(.*)(?=.html)", url).get(0);
        String reqUrl = "https://wenku.baidu.com/browse/getbcsurl?doc_id="+docId+"&pn=1&rn=99999&type=ppt";
        // 获取到ppt所有内容的信息
        String html = requests.getText(reqUrl);
        System.out.println("html = " + html);
        List<String> lists = findall("(?<=\\{\"zoom\":\")(.*?)(?=\",\"page\")", html);
        System.out.println("lists = "+lists.toString());
        for (int i = 0; i<lists.size(); i++){
            lists.set(i, lists.get(i).replace("\\",""));
            System.out.println(lists.get(i));
        }

        String sourcePath = ROOT_PATH+WENKU_PATH+PPT_PATH+"/"+docId;

        for (int j = 0; j<lists.size(); j++){
            byte[] img = readInputStream(requests.getContent(lists.get(j)));
            saveByte(sourcePath,docId+"_"+j+".jpg",img);
        }
        String zipFilePath = "zipPath";
        FileToZip.fileToZip(sourcePath, zipFilePath, docId);
    }

    public static void TXT(String url){
        TXT(url, "TXT");
    }

    /**
     * 下载txt格式的文档
     * @param url
     * @param type
     */
    public static void TXT(String url, String type){
        StringBuffer txtBuffer = new StringBuffer();

        String docId = findall("(?<=view/)(.*)(?=.html)", url).get(0);
        String reqUrl = "https://wenku.baidu.com/api/doc/getdocinfo?callback=cb&doc_id=" + docId;
        String html = requests.getText(reqUrl);
        String md5 = findall("(?<=\"md5sum\":\")(.*?)(?=\")",html).get(0);
        String pn = findall("(?<=\"totalPageNum\":\")(.*?)(?=\")",html).get(0);
        String rsign = findall("(?<=\"rsign\":\")(.*?)(?=\")",html).get(0);
        String newUrl = "https://wkretype.bdimg.com/retype/text/" + docId + "?rn=" + pn + "&type=txt" + md5 + "&rsign=" + rsign;
        String txt = requests.getText(newUrl,"utf-8",true);
        ObjectMapper objectMapper = new ObjectMapper();
        try{
            List list = objectMapper.readValue(txt,ArrayList.class);
           for (int j = 0; j < list.size(); j++){
               Map<String, Object> map = (Map)list.get(j);
               List<Map<String, Object>> paragsList = (List)map.get("parags");
               for (Map<String, Object> paragsListMap: paragsList) {
                   txtBuffer.append(paragsListMap.get("c").toString().replaceAll("\\f","\n"));
               }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        if("TXT".equals(type)){
            String sourcePath = ROOT_PATH+WENKU_PATH+TXT_PATH+"/"+docId;
            saveString(sourcePath, docId+".txt",txtBuffer.toString());
            String zipFilePath = "zipPath";
            FileToZip.fileToZip(sourcePath, zipFilePath, docId);
        }else{
            String sourcePath = ROOT_PATH+WENKU_PATH+PDF_PATH+"/"+docId;
            saveString(sourcePath, docId+".txt",txtBuffer.toString());
            String zipFilePath = "zipPath";
            FileToZip.fileToZip(sourcePath, zipFilePath, docId);
        }

    }

    public static void PDF(String url){
//        TXT(url, "PDF");
        PPT(url);
    }

    public static WenKuEntity initEntity(String url){
        String docId = findall("(?<=view/)(.*)(?=.html)", url).get(0);

        WenKuEntity wenKuEntity = new WenKuEntity();
        wenKuEntity.setDocId(docId);
        String html = requests.getText(url);
        List<String> typeList = findall("(?<=docType.{1,20}?\\:.{1,20}?\\'{1,10})(.*?)(?=\\'\\,)",html);
        //匹配文档类型
        if(typeList!=null && typeList.size()>0){
            wenKuEntity.setDocType(getWenKuDocTypeEnum(typeList.get(0)));
        }

        //匹配标题
        List<String> titilList = findall("(?<=title.{1,20}?\\:.{1,20}?\\')(.*?)(?=\\'\\,)",html);
        if(titilList!=null && titilList.size()>0){
            wenKuEntity.setDocTitle(titilList.get(0));
        }

        //匹配上传者
        List<String> createrList = findall("(?<=creater.{1,20}?\\:.{1,20}?\\')(.*?)(?=\\'\\,)",html);
        if(createrList!=null && createrList.size()>0){
            try{
                wenKuEntity.setDocAuthor(URLDecoder.decode(createrList.get(0),"gb2312"));
            }catch (Exception e){
                System.out.println(e.getMessage());;
            }
        }

        //匹配描述
        List<String> descList = findall("(?<=docDesc.{1,20}?\\:.{1,20}?\\')(.*?)(?=\\'\\,)",html);
        if(descList!=null && descList.size()>0){
            wenKuEntity.setDocDesc(descList.get(0));
        }else{
            wenKuEntity.setDocDesc("");
        }

        //匹配标签
        List<String> catsList = findall("(?<=cats.{1,20}?\\:.{1,20}?\\')(.*?)(?=\\'\\,)",html);
        if(catsList!=null && catsList.size()>0){
            wenKuEntity.setDocLabel(catsList.get(0));
        }

        //匹配文档大小
        List<String> sizeList = findall("(?<=size.{1,20}?\\:.{1,20}?\\')(.*?)(?=\\'\\,)",html);
        if(sizeList!=null && sizeList.size()>0){
            wenKuEntity.setDocSize(Integer.valueOf(sizeList.get(0)));
        }

        return wenKuEntity;

    }

    //获取文档标签
    public static String getDocLabel(int i){
        //<li class="current">面试</li>
        String html = requests.getText("https://wenku.baidu.com/list/"+String.valueOf(i));
        List<String> labelList = findall("(?<=<li class=\"current\">)(.*)(?=</li>)",html);
        if(labelList!=null && labelList.size()>0){
            return labelList.get(0);
        }else{
            return "";
        }
    }

    public static WenKuDocTypeEnum getWenKuDocTypeEnum(String docType){
        WenKuDocTypeEnum wenKuDocTypeEnum = null;
        switch (docType){
            case "doc":
                wenKuDocTypeEnum = WenKuDocTypeEnum.DOC;
                break;
            case "ppt":
                wenKuDocTypeEnum = PPT;
                break;
            case "txt":
                wenKuDocTypeEnum = WenKuDocTypeEnum.TXT;
                break;
            case "pdf":
                wenKuDocTypeEnum = WenKuDocTypeEnum.PDF;
                break;
        }
        return wenKuDocTypeEnum;
    }

    public static void main(String[] args) throws Exception{
        WenKuTool.DOC("https://wenku.baidu.com/view/18263ba4102de2bd9605885e.html?from=search");
//        WenKuTool.PPT("https://wenku.baidu.com/view/69d70fa9d0f34693daef5ef7ba0d4a7302766c6d.html?from=search");
//        WenKuTool.TXT("https://wenku.baidu.com/view/c52b42b951e2524de518964bcf84b9d528ea2cc8.html?from=search");
//        WenKuTool.PDF("https://wenku.baidu.com/view/4044152e77c66137ee06eff9aef8941ea76e4b88.html?from=search");

//        WenKuEntity entity = WenKuTool.initEntity("https://wenku.baidu.com/view/341ff300caaedd3383c4d3f9.html?from=search");
//        System.out.println(entity.toString());

//        int i = 1;
//        while(i<700){
//            String label = WenKuTool.getDocLabel(i);
//            if(!label.equals("")){
////                System.out.println(i+":"+label);
//                System.out.println("INSERT INTO `wenku_label` (`label_id`, `label_name`) VALUES ('"+ i +"', '"+ label +"');");
//            }
//            i++;
//        }

//        WenKuEntity wenKuEntity = new WenKuEntity();
//        wenKuEntity.setDocId("1111");
//        wenKuEntity.setDocType(WenKuDocTypeEnum.DOC);
//        wenKuEntity.setDocTitle("3333");

    }

}
